#include "master.h"
#include <shlwapi.h>
#include <ole2.h>
#include <dshow.h>
#include <commctrl.h>
#include <msxml2.h>
#include <stdio.h>
#include "wndproc.h"
#include "stream.h"
#include "misc.h"
#include "menu.h"
#include "systray.h"
#include "gui.h"
#include "playlist.h"
#include "operations.h"
#include "registry.h"
#include "metaparse.h"
#include "flags.h"
#include "comfunct/comfunct.h"

signed long PlayVolume = 0L;
extern IGraphBuilder *pGraph;
extern IBasicAudio   *pVolume;
extern IMediaControl *pControl;
extern IMediaSeeking *pSeek;
extern bool bCanSeek;
bool bCmdLine = false;
extern LPTSTR szVolume;
extern DWORD dwMaxSliderPos, capable;
extern REFERENCE_TIME FileTimeinNanos;
extern HANDLE hInetStreamThread;
extern HMODULE hAudioSE;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    REFERENCE_TIME rtStartTime = 0;
    static short sOptions = 0;
    static HANDLE hDownloadedStream = NULL;
	static PLAYLISTDATA pld = {0};
	static HFONT hFont = NULL;
	static HMODULE hUpdateDll = NULL;
	static HBRUSH hbrBackBrush = NULL;
    const HBRUSH hbrEditBrush = GetSysColorBrush(COLOR_3DLIGHT);
    
    switch(msg)
    {
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDI_FILE_OPEN:
                    {
                        if(pGraph != NULL)
						{
                            SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_CLOSE, 0), (LPARAM)NULL);
                        }
                        GetOpenFile(hwnd, sOptions & IS_TRAYED);
                    }        
                break;
                case IDI_FILE_PLAYLIST_OPEN:
                    {
                        DWORD dwThreadId = 0;
                        if(pGraph != NULL)
						{
                            SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_CLOSE, 0), (LPARAM)NULL);
                        }
                        SetStatus(hwnd, IDI_STATUS, 0, GetLocalText(44));
						CreateThread(NULL, 0, OpenPlaylistFile, &pld, 0, &dwThreadId);
                    }
                break;
                case IDI_FILENAME:
                    {
                        if(EN_CHANGE == HIWORD(wParam))
                        {
                            size_t FileLength = 0;
							TCHAR szFilePath[MAX_PATH] = TEXT("");
							
                            GetDlgItemText(hwnd, IDI_FILENAME, szFilePath, MAX_PATH);                            
							FileLength = _tcslen(szFilePath);
							
                            if(FileLength > 0)
                            {
                                EnableWindow(GetDlgItem(hwnd, IDI_CONT_PLAY), true);
                            }
                            else
                            {
                                EnableWindow(GetDlgItem(hwnd, IDI_CONT_PLAY), false);
                            }
                        }    
                    }    
                break;
                case ID_SEL_ALL:
                    {
                        SendDlgItemMessage(hwnd, IDI_FILENAME, EM_SETSEL, 0, -1);
                    }
                break;
                case IDI_FILE_CLOSE:
                    {
                        if(sOptions & TIMER_ON)
						{
							KillTimer(hwnd, IDT_TIMETICK);
							sOptions &= (~(TIMER_ON));
						}
						if(sOptions & SHOW_LYRICS)
						{
							SetWindowText(GetDlgItem(hwnd, IDI_LYRICS), TEXT(""));
						}
						SendDlgItemMessage(hwnd, IDI_SLIDER, TBM_SETPOS, true, 0);
						CloseStream(hwnd, &hDownloadedStream);
						if(pld.lNumOfFilesinPlaylist != 0L)
						{
							unsigned long loop = 0L;
							HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
							HWND hPlaylistTitle = GetDlgItem(hwnd, IDI_PLAYLIST_TITLE);
							RECT rc = {0};
							GetWindowRect(hwnd, &rc);
							if((rc.right - rc.left) > 400)
							{
								AdjustWindowWidth(hwnd, -(PLAYLIST_VIEW_WIDTH)); /* Collapse playlist view if it's opened */
							}
                            for(; loop < pld.lNumOfFilesinPlaylist; ++loop)
							{
								free(pld.PlaylistItems[loop]);
							}
							free(pld.PlaylistItems);
							pld.lNumOfFilesinPlaylist = 0L;
							pld.lCurrentPlayingFile = 0L;
							_tcscpy(pld.szPlaylistPath, TEXT(""));
							TogglePlaylistMenu(hwnd, false);
							ListView_DeleteAllItems(hPlaylistItems);
							SetWindowText(hPlaylistTitle, GetLocalText(6));
						}
						MSNCheckAndUpdate(hwnd, NULL, true);
						UpdateTrayToolTip(hwnd);
					}
                break;
                case IDI_FILE_EXIT:
				{
                    SendMessage(hwnd, WM_CLOSE, 0, 0);
				}
                break;
				case IDI_FILE_TOGGLESHORTCUT:
				{
					ToggleDesktopLink();
				}
				break;
                case IDI_FILE_SAVESTREAM:
                {
                    GetSavePath(hwnd);
                }
                break;
                case IDI_FILE_MUTEX:
                {
                    static HANDLE hMutex = NULL;
                    if(sOptions & INSTANCE_MUTEX)
                    {
                        MenuCheck(hwnd, FILE_MENU, IDI_FILE_MUTEX, false);
                        ReleaseMutex(hMutex);
                        CloseHandle(hMutex);
                        sOptions &= (~(INSTANCE_MUTEX));
                    }
                    else
                    {
                        MenuCheck(hwnd, FILE_MENU, IDI_FILE_MUTEX, true);
                        sOptions |= INSTANCE_MUTEX;
                        hMutex = CreateMutex(NULL, TRUE, TEXT("AudioPlayer"));
                        if(GetLastError() == ERROR_ALREADY_EXISTS)
                        {
                            ErrorMessage(GetLocalText(71));
                            SendMessage(hwnd, WM_CLOSE, 0, 0);
                        }
                    }
                }
				break;
				case IDI_FILE_PLAY_FOLDER:
				{
					return PlayFolder(hwnd, &pld);
				}
				break;
				case IDI_PLAYLIST_SHUFFLE:
					{
						if(pld.bShuffle == false)
						{
							pld.bShuffle = true;
							MenuCheck(hwnd, PLAYLIST_MENU, IDI_PLAYLIST_SHUFFLE, true);
						}
						else
						{
							pld.bShuffle = false;
							MenuCheck(hwnd, PLAYLIST_MENU, IDI_PLAYLIST_SHUFFLE, false);
						}
					}
				break;
				case IDI_PLAYLIST_NEXT:
					{
						if(pld.bShuffle == true)
						{
							pld.lCurrentPlayingFile = GetRandomTrack(&pld);
						}
						else if(pld.lCurrentPlayingFile == (pld.lNumOfFilesinPlaylist - 1)) /* We're at the end of the playlist and shuffle isn't on so we go back to the beginning */
						{
							pld.lCurrentPlayingFile = 0;
						}
						else
						{
							++pld.lCurrentPlayingFile;
						}
						CloseStream(hwnd, &hDownloadedStream);
						ProcessFile(hwnd, sOptions & IS_TRAYED, pld.PlaylistItems[pld.lCurrentPlayingFile], &pld);
					}
				break;
				case IDI_PLAYLIST_COMMANDLINE:
                    {
                        DWORD dwThreadId = 0;
                        SetStatus(hwnd, IDI_STATUS, 0, GetLocalText(44));
                        memcpy(pld.szPlaylistPath, (TCHAR*)lParam, (MAX_PATH * sizeof(TCHAR)));
						CreateThread(NULL, 0, InvokePlaylist, &pld, 0, &dwThreadId);
                    }
                break;
				case IDI_PLAYLIST_SAVEM3U:
					{
						SavePlaylist(hwnd, &pld);
					}
				break;
				case IDI_PLAYLIST_SHOW:
					{
						if(!(sOptions & SHOW_PLAYLIST))
						{
							MenuCheck(hwnd, PLAYLIST_MENU, IDI_PLAYLIST_SHOW, true);
							AdjustWindowWidth(hwnd, PLAYLIST_VIEW_WIDTH);
							sOptions |= SHOW_PLAYLIST;
						}
						else
						{
							MenuCheck(hwnd, PLAYLIST_MENU, IDI_PLAYLIST_SHOW, false);
							AdjustWindowWidth(hwnd, -(PLAYLIST_VIEW_WIDTH));
							sOptions &= (~(SHOW_PLAYLIST));
						}
					}
				break;
                case IDI_CONT_PLAY:
                    {
                        TCHAR* szStatusText = GetStatusText(hwnd, 0);
						const TCHAR* szPaused = GetLocalText(38);

                        if((_tcscmp(szStatusText, GetLocalText(59)) == 0) || (_tcscmp(szStatusText, GetLocalText(37)) == 0)) /* Opened or Stopped statuses */
                        {
                            if(SUCCEEDED(pControl->lpVtbl->Run(pControl)))
                            {
								TCHAR szPlayingFile[MAX_PATH] = TEXT("");
								if(bCanSeek == true)
                                {
                                    SetTimer(hwnd, IDT_TIMETICK, 1000, (TIMERPROC)NULL);
                                    sOptions |= TIMER_ON;
                                }
                                SetStatus(hwnd, IDI_STATUS, 0, GetLocalText(39));
								GetDlgItemText(hwnd, IDI_FILENAME, szPlayingFile, MAX_PATH);
								MSNCheckAndUpdate(hwnd, PathFindFileName(szPlayingFile), false);
								DisplayLyrics(hwnd, szPlayingFile);
                            }
							free(szStatusText);
                        }
						else if(_tcscmp(szStatusText, GetLocalText(7)) == 0) /* Ready status */
                        {
                            TCHAR szFilePath[1000] = TEXT("");                           
                            GetDlgItemText(hwnd, IDI_FILENAME, szFilePath, 1000);

                            if(PathIsURL(szFilePath) == FALSE)
						    {							
							    free(szStatusText);
                                return PlayLocalFile(hwnd, sOptions & IS_TRAYED, szFilePath);
                            }
                            else /* if it is a URL */
                            {
                                bool IsMP3 = IsMPEGAudio(szFilePath);
                                
                                free(szStatusText);
                                OpenMP3URL(hwnd, szFilePath, IsMP3);
                                if(IsMP3 == false)
                                {
                                    return PlayNonMP3URL(hwnd, szFilePath, &hDownloadedStream, capable);
                                }
                            }
                        }
						else if(_tcscmp(szStatusText, szPaused) == 0) /* Paused */
                        {
                            TogglePause(hwnd, &sOptions, false);
							free(szStatusText);
                        }
						if(sOptions & IS_TRAYED)
						{
                            UpdateTrayToolTip(hwnd);
                        }
                        return 0;
                    }    
                break;
                case IDI_CONT_PAUSE:
                    {
                        if(lParam == 0xDEAD)
						{
							return TogglePause(hwnd, &sOptions, true);
						}
						else return TogglePause(hwnd, &sOptions, false);
                    }    
                break;
                case IDI_CONT_STOP:
                    {
                        return StopStream(hwnd, &sOptions, rtStartTime);
                    }
                break;
                case IDI_CONT_LOOP:
                {
                     if(!(sOptions & LOOP_AUDIO))
                     {
                         MenuCheck(hwnd, CONTROL_MENU, IDI_CONT_LOOP, true);
                         sOptions |= LOOP_AUDIO;
                     }
                     else
                     {
                         MenuCheck(hwnd, CONTROL_MENU, IDI_CONT_LOOP, false);
						 sOptions &= (~(LOOP_AUDIO));
                     }
                }
                break;
				case IDI_CONT_CHANGEBACKCOLOR:
				{
					 RECT rc = {0};
					 ChangeBackgroundColor(hwnd, &hbrBackBrush);
					 GetClientRect(hwnd, &rc);
					 InvalidateRect(hwnd, &rc, false);
					 EnumChildWindows(hwnd, SetChildWindowsTransparency, 0); /* Goes through all the child windows and sends the appropriate WM_CTLCOLOR* messages to set their background transparency */
				}
				break;
				case IDI_DISPLAY_LYRICS:
				{
					if(!(sOptions & SHOW_LYRICS))
					{
						MenuCheck(hwnd, CONTROL_MENU, IDI_DISPLAY_LYRICS, true);
						AdjustWindowHeight(hwnd, 200);
						sOptions |= SHOW_LYRICS;
						if(lParam != 1)
						{
							return LyricsHandler(hwnd);
						}
					}
					else
					{
						MenuCheck(hwnd, CONTROL_MENU, IDI_DISPLAY_LYRICS, false);
						AdjustWindowHeight(hwnd, -200);
						sOptions &= (~(SHOW_LYRICS));
					}
                }
                break;
                case IDI_FILE_MINTOTRAY:
                {
                     if(sOptions & TRAY_MINIMIZE)
                     {
                          MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, false);
						  sOptions &= (~(TRAY_MINIMIZE));
                     }
                     else
                     {
                          MenuCheck(hwnd, FILE_MENU, IDI_FILE_MINTOTRAY, true);
                          sOptions |= TRAY_MINIMIZE;
                     }
                }
                break;
                case IDI_VOL_MUTE:
                    {
                        if(GetMute() == true)
                        {
                            SetMute(false);
                            SetStatus(hwnd, IDI_STATUS, 2, szVolume);
                            UpdateTrayToolTip(hwnd);
                        }
                        else
                        {
                            SetMute(true);
                            SetStatus(hwnd, IDI_STATUS, 2, GetLocalText(15));
                            UpdateTrayToolTip(hwnd);
                        }
                    }
                break;
                case IDI_VOL_FULL:
                    {
                        SendDlgItemMessage(hwnd, IDI_VOLUME, TBM_SETPOS, true, 0);
                        PlayVolume = 0L;
                        pVolume->lpVtbl->put_Volume(pVolume, PlayVolume);
                        szVolume = VolumeTextFromLong(PlayVolume, szVolume);
                        SetStatus(hwnd, IDI_STATUS, 2, szVolume);
                        if(GetMute() == true)
                        {
                             SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_VOL_MUTE, 0), (LPARAM)NULL);
                        }

                        if(sOptions & IS_TRAYED)
                        {
                            UpdateTrayToolTip(hwnd);
                        }
                    }    
                break;  
                case IDI_VOL_HALF:
                    {
                        PlayVolume = VOLUME_MUTE / 2;
                        SendDlgItemMessage(hwnd, IDI_VOLUME, TBM_SETPOS, true, (PlayVolume * -1));
                        pVolume->lpVtbl->put_Volume(pVolume, PlayVolume);
                        szVolume = VolumeTextFromLong(PlayVolume, szVolume);
                        SetStatus(hwnd, IDI_STATUS, 2, szVolume);
                        if(GetMute() == true)
                        {
                             SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, IDI_VOL_MUTE), (LPARAM)NULL);
                        }

                        if(sOptions & IS_TRAYED)
                        {
                            UpdateTrayToolTip(hwnd);
                        }
                    }    
                break;
				case IDI_TOOLS_REGISTER:
					{
						RegisterPlaylistFormat(hwnd);
					}
				break;
				case IDI_TOOLS_UNREGISTER:
					{
						UnRegisterExtensions(hwnd);
					}
				break;
				case IDI_TOOLS_ALWAYSONTOP:
                    {
                        static bool bAlwaysOnTop = false;
						if(bAlwaysOnTop == false)
                        {
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_ALWAYSONTOP, true);
                            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
                            bAlwaysOnTop = true;
                        }
                        else
                        {
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_ALWAYSONTOP, false);
                            SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
                            bAlwaysOnTop = false;
                        }
                    }
                break;
				case IDI_TOOLS_MSN:
					{
						static bool bMSNChecked = false;
						if(bMSNChecked == false)
                        {
                            TCHAR* szSongTitle = NULL;
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_MSN, true);
                            bMSNChecked = true;
                            szSongTitle = GetStatusText(hwnd, 1);
                            MSNCheckAndUpdate(hwnd, szSongTitle, false);
                            free(szSongTitle);
                        }
                        else
                        {
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_MSN, false);
							bMSNChecked = false;
							MSNCheckAndUpdate(hwnd, NULL, true);
                        }
					}
				break;
				case IDI_TOOLS_HOTKEYS:
                    {
                        if(!(sOptions & HOTKEYS_ON))
                        {
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_HOTKEYS, true);
                            ToggleHotKeys(hwnd, true);
                            sOptions |= HOTKEYS_ON;
                        }
                        else
                        {
                            MenuCheck(hwnd, TOOLS_MENU, IDI_TOOLS_HOTKEYS, false);
                            ToggleHotKeys(hwnd, false);
							sOptions &= (~(HOTKEYS_ON));
                        }
                    }
                break;

#ifdef UNICODE /* Media Key control only available on 2000/XP */

				case IDI_TOOLS_MEDIAHOOK:
				{
					return ToggleHook(hwnd, &sOptions);
				}
				break;

#endif

                case IDI_HELP_ABOUT:
                    {
                        CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ABOUT), hwnd, (DLGPROC)AboutDlgProc);
                    }
                break;
                case IDI_HELP_LOGOFF:
                     {
                        if(MessageBox(hwnd, GetLocalText(72), GetLocalText(73), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
                        ExitWindowsEx(EWX_LOGOFF, 0);
                     }
                break;
                case IDI_HELP_REBOOT:
                     {
                        if(MessageBox(hwnd, GetLocalText(74), GetLocalText(75), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
                        ExitWindowsEx(EWX_REBOOT, 0);
                     }
                break;
                case IDI_HELP_SHUTDOWN:
                     {
                        if(MessageBox(hwnd, GetLocalText(76), GetLocalText(77), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2) == IDYES)
                        ExitWindowsEx(EWX_SHUTDOWN, 0);
                     }
                break;
                case IDI_HELP_VISITSITE:
                     {
                        ShellExecute(hwnd, TEXT("open"), TEXT("http://audioplayer.sourceforge.net/"), NULL, NULL, SW_SHOW);
                     }
                break;
                case IDI_HELP_BUG_REPORT:
                     {
                        ShellExecute(hwnd, TEXT("open"), TEXT("http://sourceforge.net/tracker/?group_id=156633&atid=800564"), NULL, NULL, SW_SHOW);
                     }
                break;
                case IDI_HELP_REQUEST_FEATURE:
                     {
                        ShellExecute(hwnd, TEXT("open"), TEXT("http://sourceforge.net/tracker/?group_id=156633&atid=800567"), NULL, NULL, SW_SHOW);
                     }
                break;
				case IDI_HELP_CHECKFORUPDATES:
					{
						if(CheckForUpdates(hwnd, &hUpdateDll) == false)
						{
							FreeLibrary(hUpdateDll);
							hUpdateDll = NULL;
						}
					}
				break;
                case IDI_TRAY_SHOW_WINDOW:
                     {
                         ShowWindow(hwnd, SW_SHOWMINIMIZED);
                         ShowWindow(hwnd, SW_RESTORE);
                         DeleteTrayIcon(hwnd);
                         sOptions &= (~(IS_TRAYED));
                     }
                break;
				case IDI_PV_PLAY_TRACK:
					{
						NMITEMACTIVATE nmItem = {0};
						HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
						nmItem.hdr.code = NM_DBLCLK;
						nmItem.hdr.hwndFrom = hPlaylistItems;
						nmItem.iItem = ListView_GetSelectionMark(hPlaylistItems);
						SendMessage(hwnd, WM_NOTIFY, IDI_PLAYLIST_VIEW, (LPARAM)&nmItem);
					}
				break;
				case IDI_PV_COPY_TITLE:
					{
						TCHAR szText[500] = TEXT("");
						HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
						LVITEM lvi = {0};

						lvi.mask = LVIF_TEXT;
						lvi.pszText = szText;
						lvi.cchTextMax = 500;
						GetPVSelection(hPlaylistItems, &lvi);
						CopyData(hwnd, szText);
					}
				break;
				case IDI_PV_COPY_PATH:
					{
						HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
						LVITEM lvi = {0};
						TCHAR* szPath = NULL;

						lvi.mask = LVIF_PARAM;
						GetPVSelection(hPlaylistItems, &lvi);
						szPath = pld.PlaylistItems[lvi.lParam];

						if(PathIsRelative(szPath) == TRUE)
						{
							TCHAR szFullPath[MAX_PATH] = TEXT("");
							GetFullPathName(szPath, MAX_PATH, szFullPath, NULL);
							CopyData(hwnd, szFullPath);
						}
						else CopyData(hwnd, szPath);
					}
				break;
				case IDI_PV_OPEN_FOLDER:
					{
						HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);
						LVITEM lvi = {0};
						TCHAR* szPath = NULL;

						lvi.mask = LVIF_PARAM;
						GetPVSelection(hPlaylistItems, &lvi);
						szPath = pld.PlaylistItems[lvi.lParam];
						PathRemoveFileSpec(szPath);
						ShellExecute(hwnd, TEXT("open"), szPath, NULL, NULL, SW_SHOWNORMAL);
					}
				break;
				case IDI_PV_REMOVE_TRACK:
					{
						LVITEM lvi = {0};
						HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);

						if(lParam == 0xDEAD)
						{
							LVFINDINFO lvf = {0};
							lvf.flags = LVFI_PARAM;
							lvi.lParam = HIWORD(wParam);
							lvf.lParam = lvi.lParam;
							lvi.iItem = ListView_FindItem(hPlaylistItems, -1, &lvf);
						}
						else
						{
							lvi.mask = LVIF_PARAM;
							GetPVSelection(hPlaylistItems, &lvi);
						}
						ListView_DeleteItem(hPlaylistItems, lvi.iItem);
						if(ListView_GetItemCount(hPlaylistItems) == 0)
						{
							/* If there are no more items in the playlist, close it and clean up */
							SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_CLOSE, 0), 0);
						}
						else
						{
							free(pld.PlaylistItems[lvi.lParam]);
							pld.PlaylistItems[lvi.lParam] = malloc((_tcslen(TEXT("")) + 1) * sizeof(TCHAR));
							_tcscpy(pld.PlaylistItems[lvi.lParam], TEXT(""));
						}
					}
				break;
				case IDI_PV_DELETE_TRACK:
					{
						if(MessageBox(hwnd, GetLocalText(78), GetLocalText(79), MB_YESNO) == IDYES)
						{
							TCHAR szFile[MAX_PATH] = TEXT("");
							LVITEM lvi = {0};
							HWND hPlaylistItems = GetDlgItem(hwnd, IDI_PLAYLIST_VIEW);

							lvi.mask = LVIF_PARAM;
							GetPVSelection(hPlaylistItems, &lvi);
							DeleteFile(pld.PlaylistItems[lvi.lParam]);
							SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_PV_REMOVE_TRACK, 0), 0);
						}
					}
				break;
            }
        break;
        case WM_CREATE:
            {
                HMENU hMenu = GetMenu(hwnd), hToolsMenu = GetSubMenu(hMenu, TOOLS_MENU);
				hbrBackBrush = GetSysColorBrush(COLOR_WINDOW);
				/*if(bCmdLine == false)
				{
					ReadOptionsAndConfigure(hwnd, &sOptions);
				}*/
                
                ShutdownPrivilege();
                ControlCreate(hwnd);
                
                if(AreTypesRegistered() == true)
                {
                    EnableMenuItem(hToolsMenu, IDI_TOOLS_UNREGISTER, MF_ENABLED);
                }
                else
                {
                    EnableMenuItem(hToolsMenu, IDI_TOOLS_REGISTER, MF_ENABLED);;
                }
				CheckAndFixOpenWith();
                return 0;
            }    
        break;
        case WM_HSCROLL:
            {
                   if((LOWORD(wParam) == TB_THUMBTRACK || 
			       LOWORD(wParam) == TB_PAGEDOWN ||
			       LOWORD(wParam) == TB_LINEUP ||
			       LOWORD(wParam) == TB_LINEDOWN ||
			       LOWORD(wParam) == TB_PAGEUP ||
			       LOWORD(wParam) == TB_TOP ||
                   LOWORD(wParam) == TB_BOTTOM) &&
                   pGraph != NULL)
                   {
                       LRESULT dwpos = SendDlgItemMessage(hwnd, IDI_SLIDER, TBM_GETPOS, 0, 0);
                       REFERENCE_TIME rtCurTime = (FileTimeinNanos/100) * dwpos;
                       pSeek->lpVtbl->SetPositions(pSeek, &rtCurTime, AM_SEEKING_AbsolutePositioning,
                                           NULL, AM_SEEKING_NoPositioning);
                       ElapsedTimeUpdate(hwnd, rtCurTime);
                   }
                   return 0; 
            }
        break;
        case WM_DROPFILES:
            {
                return ParseDroppedFile(hwnd, wParam, &pld);                
            }
        break;
        case WM_VSCROLL:
            {
                if((LOWORD(wParam) == TB_THUMBTRACK || 
                   LOWORD(wParam) == TB_BOTTOM ||
			       LOWORD(wParam) == TB_PAGEDOWN ||
			       LOWORD(wParam) == TB_PAGEUP ||
			       LOWORD(wParam) == TB_LINEUP ||
			       LOWORD(wParam) == TB_LINEDOWN ||
			       LOWORD(wParam) == TB_TOP) &&
                   pGraph != NULL)
                   {
                       PlayVolume = ((signed long)SendDlgItemMessage(hwnd, IDI_VOLUME, TBM_GETPOS, 0, 0) * -1);
                       szVolume = VolumeTextFromLong(PlayVolume, szVolume);
                       if(PlayVolume == VOLUME_MUTE)
                       {
                            SetMute(true);
                       }
                       else
                       {
                            pVolume->lpVtbl->put_Volume(pVolume, PlayVolume);
                       }
					   SetStatus(hwnd, IDI_STATUS, 2, szVolume);

					   if(sOptions & IS_TRAYED)
					   {
                            UpdateTrayToolTip(hwnd);
                       }
                   }
                   return 0;
            }
        break;
        case WM_TIMER:
             {
                if(pGraph != NULL)
                {
                    DWORD dwCurrentSliderPos = 0;
                    REFERENCE_TIME timeNow = 0LL;

					dwCurrentSliderPos = (DWORD)SendDlgItemMessage(hwnd, IDI_SLIDER, TBM_GETPOS, 0, 0);
                    if(dwCurrentSliderPos < dwMaxSliderPos)
                    {
                        if(SUCCEEDED(pSeek->lpVtbl->GetCurrentPosition(pSeek, &timeNow)))
                        {
                            long sliderTick = (long)((timeNow * 100) / FileTimeinNanos);
                            SendDlgItemMessage(hwnd, IDI_SLIDER, TBM_SETPOS, true, sliderTick);
                            ElapsedTimeUpdate(hwnd, timeNow);
                        }
                    }
                    else if(dwCurrentSliderPos >= dwMaxSliderPos)
                    {
                        if(sOptions & CLOSE_WHEN_FINISHED)
                        {
                            SendMessage(hwnd, WM_CLOSE, 0, 0);
                            return 0;
                        }

						KillTimer(hwnd, IDT_TIMETICK);
						sOptions &= (~(TIMER_ON));
						
                        pControl->lpVtbl->Stop(pControl);
                        pSeek->lpVtbl->SetPositions(pSeek, &rtStartTime, AM_SEEKING_AbsolutePositioning,
                                                    NULL, AM_SEEKING_NoPositioning);
                        SendDlgItemMessage(hwnd, IDI_SLIDER, TBM_SETPOS, true, 0);
                        pSeek->lpVtbl->GetCurrentPosition(pSeek, &timeNow);
                        ElapsedTimeUpdate(hwnd, timeNow);

                        if(sOptions & LOOP_AUDIO)
                        {
                           SetTimer(hwnd, IDT_TIMETICK, 1000, (TIMERPROC)NULL);
                           sOptions |= TIMER_ON;
                           pControl->lpVtbl->Run(pControl);
                           pVolume->lpVtbl->put_Volume(pVolume, PlayVolume);
                        }
						else if(pld.lNumOfFilesinPlaylist != 0)
                        {
                           SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_PLAYLIST_NEXT, 0), (LPARAM)NULL);
                        }
						else
                        {
                           SetStatus(hwnd, IDI_STATUS, 0, GetLocalText(37));
                           if(sOptions & IS_TRAYED)
                           {
                               UpdateTrayToolTip(hwnd);
                           }
                        }
                    }
                }
             }
        break;
        case WM_CTLCOLORSTATIC:
        case WM_CTLCOLORBTN:
		case WM_CTLCOLORLISTBOX:
        {
             HDC hdcStatic = (HDC)wParam;
             SetBkMode(hdcStatic, TRANSPARENT);
             return (LRESULT)hbrBackBrush;
        }
        break;
        case WM_CTLCOLOREDIT:
        {
             HDC hdcStatic = (HDC)wParam;
             SetBkMode(hdcStatic, TRANSPARENT);
             return (LRESULT)hbrEditBrush;
        }
        break;
		case WM_PAINT:
		{
			 HDC hdc = NULL;
			 PAINTSTRUCT ps = {0};
			 RECT rc = {0};

			 GetClientRect(hwnd, &rc);

			 hdc = BeginPaint(hwnd, &ps);
			 FillRect(hdc, &rc, hbrBackBrush);
			 EndPaint(hwnd, &ps);
		}
		break;
		case WM_NOTIFY:
		{
			return NotifyMessage(hwnd, lParam, &pld, sOptions);
		}
		break;
        case WM_FREEMEMMAP:
        {
            UnmapMemory();
        }
        break;
        case WM_CLOSESTREAM:
        {
             CloseStream(hwnd, &hDownloadedStream); 
        }
        break;
		case WM_FILEREADY:
		{
			return PrepareAndPlayMP3Stream(hwnd, lParam, sOptions & IS_TRAYED, &hDownloadedStream);
		}
		break;
        case WM_ASETHREADFINISHED:
        {
            Sleep(100);
            CloseHandle(hInetStreamThread);
            FreeLibrary(hAudioSE);
        }
        break;
		case WM_MAKEPLAYLIST:
		{
			DWORD dwThreadId = 0;
            RAWDATA* rd = (RAWDATA*)wParam;
			rd->pld = &pld;
			SetStatus(hwnd, IDI_STATUS, 0, GetLocalText(44));
			CreateThread(NULL, 0, RawDataToPlaylist, rd, 0, &dwThreadId);           
		}
		break;
        case WM_SIZE:
        {
             if(wParam == SIZE_MINIMIZED && (sOptions & TRAY_MINIMIZE))
             {
				  TCHAR* szStatusText = GetStatusText(hwnd, 0), szIconMessage[64] = TEXT("");
                  TCHAR* szFileTitle = GetStatusText(hwnd, 1);

				  sOptions |= IS_TRAYED;
                  _sntprintf(szIconMessage, 64, TEXT("%s : %s : %s"), szStatusText, szFileTitle, szVolume);
                  AddTrayIcon(hwnd, szIconMessage);
				  free(szFileTitle);
				  free(szStatusText);
             }
        }
        break;

#ifdef UNICODE

		/* This message only available in NT/XP versions */

		case 0x0319: //WM_APPCOMMAND not defined in my version of mingw's windows headers
		{
			return AppCommand(hwnd, lParam);
		}
		break;

#endif

        case IDM_SYSTRAY_MESSAGE:
        {
             switch(lParam)
             {
                  case WM_LBUTTONDOWN:
                  {
                       ShowWindow(hwnd, SW_SHOWMINIMIZED);
                       ShowWindow(hwnd, SW_RESTORE);
                       DeleteTrayIcon(hwnd);
                       sOptions &= (~(IS_TRAYED));
                  }
                  break;
                  case WM_RBUTTONDOWN:
                  {
                       HMENU hPopup = NULL;
                       hPopup = MakePopupMenu(hwnd, sOptions & LOOP_AUDIO, pControl, &pld);
                       DestroyMenu(hPopup);
                  }
                  break;
             }
        }
        break;
        case WM_HOTKEY:
        {
             switch(HIWORD(lParam))
             {
                 case 0x4F: /* 'o' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_OPEN, 0), 0);
                 }
                 break;
                 case 0x50: /* 'p' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_CONT_PLAY, 0), 0);
                 }
                 break;
                 case 0x55: /* 'u' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_CONT_PAUSE, 0), 0);
                 }
                 break;
                 case 0x53: /* 's' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_CONT_STOP, 0), 0);
                 }
                 break;
                 case 0x59: /* 'y' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_PLAYLIST_OPEN, 0), 0);
                 }
                 break;
                 case 0x4D: /* 'm' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_VOL_MUTE, 0), 0);
                 }
                 break;
                 case VK_F4: /* F4 key */
                 {
                      SendMessage(hwnd, WM_CLOSE, 0, 0);
                 }
                 break;
                 case 0x56: /* 'v' key */
                 {
                      SendMessage(hwnd, WM_NULL, AP_SHOW, 0);
                 }
                 break;
                 case 0x4C: /* 'l' key */
                 {
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_CONT_LOOP, 0), 0);
                 }
                 break;
                 case 0x4E: /* 'n' key */
                 {
                      if(pld.lNumOfFilesinPlaylist != 0L)
                      {
                          SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_PLAYLIST_NEXT, 0), 0);
                      }
                 }
                 break;

             }
        }
        break;
        case WM_NULL:
        {
             switch(wParam)
             {
                 case AP_SHOW:
                 {
                      ShowWindow(hwnd, SW_SHOWNORMAL);
                      UpdateWindow(hwnd);
                 }
                 break;
                 case AP_CLOSE:
                 {
                      SendMessage(hwnd, WM_CLOSE, 0, 0);
                 }
                 break;
                 case AP_HIDE:
                 {
                      ShowWindow(hwnd, SW_HIDE);
                      SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_TOOLS_HOTKEYS, 0), 0);
                 }
                 break;
                 case AP_TRAY:
                 {
					  sOptions |= TRAY_MINIMIZE;
					  sOptions |= IS_TRAYED;
                 }
                 break;
                 case AP_LOOP:
                 {
                      sOptions |= LOOP_AUDIO;
                      MenuCheck(hwnd, CONTROL_MENU, IDI_CONT_LOOP, true);
                 }
                 break;
                 case AP_CLOSEONFINISH:
                 {
                      sOptions |= CLOSE_WHEN_FINISHED;
                 }
                 break;
             }
        }
        break;
        case WM_COPYDATA:
        {
            COPYDATASTRUCT* pCds = (COPYDATASTRUCT*)lParam;
            SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDI_FILE_CLOSE, 0), 0);
            ProcessFile(hwnd, sOptions & IS_TRAYED, pCds->lpData, NULL);
        }
        break;
        case WM_CLOSE:
        { 
			 CloseStream(hwnd, &hDownloadedStream);
			 //SaveOptions(sOptions);
             Cleanup(hwnd, sOptions);
             if(hFont != NULL)
             {
                 DeleteObject(hFont);
             }
             OleUninitialize();
			 if(szVolume != NULL)
			 {
				 free(szVolume);
			 }
			 DestroyWindow(hwnd);
        }    
        break;
        case WM_QUERYENDSESSION:
        {
             PostMessage(hwnd, WM_CLOSE, 0, 0);
             return true;
        }
        break;
        case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

bool CALLBACK AboutDlgProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
    static HMODULE hAudioPlayer = NULL;
    switch(Message)
    {
        case WM_INITDIALOG:
		{
			hAudioPlayer = GetModuleHandle(NULL);
            return true;
		}
        break;
        case WM_COMMAND:
		{
            switch(LOWORD(wParam))
            {
                case IDOK:
                {
                     DestroyWindow(hDialog);
                }
                break;
            }
		}
        break;
        case WM_PAINT:
        {
			PAINTSTRUCT ps = {0};
			WNDCLASS wc = {0};
			HDC hdc = BeginPaint(hDialog, &ps);
			GetClassInfo(hAudioPlayer, TEXT("AudioPlayer"), &wc);
            DrawIconEx(hdc, 295, 35, wc.hIcon, 0, 0, 0, NULL, DI_DEFAULTSIZE | DI_NORMAL);
            EndPaint(hDialog, &ps);
            return false;
        }
        break;
        default:
		{
            return false;
		}
    }
    return true;
}
